"use client";
import { Image as AntdImage, Dropdown } from "antd";
import { ReloadOutlined } from "@ant-design/icons";
import { useEffect, useState, FC, PropsWithChildren, useRef } from "react";
import { cn, sn } from "@/lib/util";
import { ImageProps, ImageGroupProps } from "./type";
import SmallText from "../../UI/SmallText";
import Loading from "../../UI/Loading";
import useLazyLoad from "@/hooks/lazyLoad";
import { ColorImageIcon } from "../../UI/MyIcon";
/**图片组件，支持加载前占位符、加载失败占位符、懒加载。预览模式基于Antd的Image组件*/
const Image = ({
  src = "",
  preview = false,
  width: _width,
  height,
  rootStyle = {},
  rootClassName,
  outStyle = {},
  outClassName,
  onClick,
  bgColor = "#f5f5f5",
  contextMenu,
  lazy = true,
  predictHeight,
}: ImageProps) => {
  /**本组件最外层的ref */
  const outRef = useRef<HTMLDivElement>(null);
  const [realSrc, setRealSrc] = useState<string>(); //存放展示的src，如果还没到视口就不展示
  const [loaded, setLoaded] = useState(false); //是否加载完成 （包含成功和失败，用于loading状态）
  const [err, setErr] = useState(false); //是否加载失败
  const [width, setWidth] = useState(_width || 0); //图片宽度
  const lazyRef = useRef(lazy);

  ///懒加载主逻辑 即使外部设置了不需要懒加载，还是会调用这个回调函数，不过没什么副作用。
  useLazyLoad(outRef, () => {
    setRealSrc(src);
    lazyRef.current = false; //懒加载仅一次
  });

  useEffect(() => {
    //不需要懒加载的，就立即加载
    if (!lazyRef.current) {
      // console.log("立即加载 ");
      setRealSrc(src);
      setTimeout(() => {
        setLoaded(true); //开发服务器热更新后不会触发onload，手动触发
      }, 500);
    }
    return () => {
      setLoaded(false);
      setRealSrc(undefined);
      setErr(false);
    };
  }, [src]);

  //设置宽度
  useEffect(() => {
    //没有传递宽度，就用父级别宽度，没有父级就200
    if (!_width) {
      const fatherWidth = outRef.current?.parentElement?.offsetWidth;
      setWidth(fatherWidth || 200);
    } else {
      setWidth(_width);
    }
  }, [_width]);

  /**加载失败时，点击可以尝试重新加载图片 */
  const reload = () => {
    setLoaded(false);
    setErr(false);
    setRealSrc(src + "?" + new Date().getTime());
  };

  return (
    <div
      ref={outRef}
      className={cn(
        outClassName,
        "relative rounded-md overflow-hidden flexCenter flex-col"
        // preview && "transition-all duration-300 border-none hover:scale-105" //预览模式时，放大的只能是最外侧，不能是图片本身放大，否则会出闪屏bug
      )}
      style={sn(outStyle, {
        width: `${width}px`,
        height: loaded ? height : `${predictHeight || height || width}px`,
        backgroundColor: loaded && !err ? "transparent" : bgColor,
      })}
    >
      {/* 加载中 */}
      {(!loaded || !realSrc) && (
        <div className={cn(rootClassName, "absolute w-full h-full flexCenter")} style={sn(rootStyle)}>
          <Loading>{/* <ColorImageIcon size={60} /> */}</Loading>
        </div>
      )}

      {/* 正常展示图片 */}
      {!err && realSrc && (
        <Dropdown menu={{ items: contextMenu }} trigger={contextMenu && contextMenu.length ? ["contextMenu"] : []}>
          <AntdImage
            alt=""
            width={width}
            loading="eager"
            height={height}
            src={realSrc || "srcIsUndefined"}
            fallback={defaultSrc} //容错处理：nextjs首屏的图片组件，不会触发onError事件，故需要这个来进行容错
            preview={preview && loaded}
            style={sn(rootStyle, { display: loaded ? "block" : "none" })} //只有加载成功才显示
            rootClassName={cn(rootClassName, !preview && "transition-all duration-300 border-none hover:scale-110")} //预览模式时，使用hover样式会导致闪屏bug
            onClick={onClick}
            onLoad={() => {
              // console.log("@加载成功", realSrc);
              setLoaded(true);
            }}
            onError={() => {
              // console.log("加载失败", realSrc);
              setErr(true);
              setLoaded(true);
            }}
          />
        </Dropdown>
      )}

      {/* 加载失败 */}
      {err && (
        <div
          className={cn(rootClassName, `w-full h-full flexCenter flex-col outBox`)}
          style={sn(rootStyle, { height: `${predictHeight || height || width}px` })}
        >
          {/* <img src="/logo.png" className="my-2" style={{ width: `${width / 3.5}px`, height: `${width / 3.5}px` }} alt="加载失败" /> */}
          <ColorImageIcon size={width / 3.5} />
          {width > 90 && <SmallText className="my-2">图片加载失败</SmallText>}
          <ReloadOutlined onClick={reload} className="cursor-pointer" style={{ color: "#8e99a9" }} />
        </div>
      )}
    </div>
  );
};
export default Image;

/** Antd的Image.PreviewGroup， 封装便于统一使用。 内部需要搭配Image组件使用*/
export const ImagePreviewGroup: React.FC<PropsWithChildren<ImageGroupProps>> = (props) => {
  const { preview, children, items, fallback = defaultSrc } = props;
  return (
    <AntdImage.PreviewGroup preview={preview} items={items} fallback={fallback}>
      {children}
    </AntdImage.PreviewGroup>
  );
};
/**默认的图片路径 */
export const defaultSrc =
  "";
